package com.qikux.controller;

import cn.hutool.http.server.HttpServerResponse;
import com.qikux.constraint.RssConst;
import com.qikux.entity.User;
import com.qikux.service.UserService;
import com.qikux.vo.LoginVo;
import com.qikux.vo.R;
import org.haredot.annotation.*;
import org.haredot.utils.MD5Utils;
import org.haredot.utils.WebUtils;
import org.haredot.web.ModelAndView;
import org.haredot.web.RequestMethod;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class LoginController {

    @Resource
    private UserService userService ;


    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login() {

        return new ModelAndView("login");
    }

    @RequestMapping(value="/login", method = RequestMethod.POST)
    public @ResponseBody R<User> login(@RequestBody LoginVo loginVo, HttpSession session) {
        // 将 LoginVo 中的输出放入到 User 中
        User user = User.builder()
                .tel(loginVo.getUsername())
                .password(loginVo.getPassword())
                .build();

        // 调用业务逻辑层处理业务，完成用户的登录操作
        R<User> ret = userService.login(user);

        if (ret.isSuccess()) {
            User data = ret.getData();
            // 如果登录成功，将用户信息存储到 Session 中
            session.setAttribute(RssConst.CURRENT_USER, data);

            // 如果 勾选了 自动登录 ，那么 需要 向 浏览器 写入一个 Cookie , 键 为 remember-me , 值为
            // Base64(用户名 +  ”:“  +  UUID  + ":"  +  MD5(  用户名 + ”:“  + UUID + ":"  + key + ":" + 密码(密文) ))
            if (loginVo.isRememberMe()) {

                String tel = data.getTel();
                String uuid = UUID.randomUUID().toString() ;
                String password = data.getPassword();

                MessageFormat messageFormat = new MessageFormat("{0}:{1}:{2}:{3}");
                String format = messageFormat.format(new Object[]{tel, uuid, RssConst.KEY, password});

                messageFormat.applyPattern("{0}:{1}:{2}");
                String format1 = messageFormat.format(new Object[]{tel, uuid, MD5Utils.md5(format)});

                // 进行 BASE64 编码
                String message = Base64.getEncoder().encodeToString(format1.getBytes(StandardCharsets.UTF_8));

                // 创建一个 Cookie 对象
                Cookie cookie = new Cookie(RssConst.REMEMBER_ME , message);
                cookie.setPath("/"); // 必须设置，否则会产生多个 remember-me 在不同的 path下
                // 设置 Cookie 的存活时间，默认为 一周 , 单位秒
                cookie.setMaxAge((int)TimeUnit.DAYS.toSeconds(7));

                // 存储 Cookie
                WebUtils.getResponse().addCookie(cookie);
            }

            data.setPassword(null);
        }
        return ret ;
    }

    /**
     *  Session的工作原理
     *
     *    当 使用 session的时候 (request.getSession()) , 服务器 会从 浏览器中
     *    查找 name = JSESSIONID 的 Cookie
     *       如果找到了，则 根据 Cookie 的 value (session的ID) 值 从 服务器找到对应的 session
     *
     *       如果 没有找到 ， 则 服务器 会创建一个 Session对象， 并将 Session对象的 ID 写入到
     *       浏览器中 ， 键为 JSESSIONID , 值为 sessionID
     *
     *   Servlet 中 Session 的默认存活时间 是 30分钟
     *      1. 可以通过 session.setMaxInactiveInterval(n) 设置存活时间， 单位是 秒
     *
     *      2. 可以 在 web.xml 中 设置 session存活时间 , 单位是 分钟
     *          <session-config>
     *              <session-timeout>30</session-timeout>
     *          </session-config>
     *
     */

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ModelAndView logout(HttpSession session, HttpServletResponse response) {
        // 1. 清除 session 中 登录标记 (不推荐)， 通常是 销毁 Session
        session.invalidate();
        // 2. 删除 所有的Cookie
        Cookie[] cookies = WebUtils.getRequest().getCookies();

        Arrays.stream(cookies).forEach(cookie ->  {
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        });

        // 3. 跳转到登录页面
        return new ModelAndView("redirect:/login");
    }

}
